#include <SoftwareSerial.h>

// 定义软件串口：Arduino D2(RX)接ESP8266 TX，D3(TX)接ESP8266 RX
SoftwareSerial espSerial(2, 3);  

// WiFi网络配置参数
const char* wifiSSID = "你的WiFi名称";  // 替换为实际WiFi名称
const char* wifiPWD = "你的WiFi密码";   // 替换为实际WiFi密码
const int tcpPort = 8080;               // TCP服务器端口
int clientID = -1;                      // 存储当前连接的客户端ID

void setup() {
  Serial.begin(115200);      // 调试串口
  espSerial.begin(115200);   // ESP8266通信串口
  
  delay(1000);
  Serial.println("开始初始化ESP8266模块...");
  
  // 1. 配置WiFi为STA模式
  String response = sendATCommand("AT+CWMODE=1", 2000);
  if (response.indexOf("OK") == -1) {
    Serial.println("设置STA模式失败");
  }
  
  // 2. 连接WiFi网络
  String connectCmd = "AT+CWJAP=\"" + String(wifiSSID) + "\",\"" + String(wifiPWD) + "\"";
  response = sendATCommand(connectCmd, 10000);
  if (response.indexOf("OK") == -1) {
    Serial.println("WiFi连接失败");
  }
  
  // 3. 获取IP地址
  response = sendATCommand("AT+CIFSR", 2000);
  Serial.println("设备网络信息：" + response);
  
  // 4. 开启多连接模式
  response = sendATCommand("AT+CIPMUX=1", 2000);
  if (response.indexOf("OK") == -1) {
    Serial.println("开启多连接失败");
  }
  
  // 5. 启动TCP服务器
  response = sendATCommand("AT+CIPSERVER=1," + String(tcpPort), 2000);
  if (response.indexOf("OK") != -1) {
    Serial.println("TCP服务器启动成功，监听端口：" + String(tcpPort));
    Serial.println("等待客户端连接...");
  } else {
    Serial.println("TCP服务器启动失败");
  }
}

void loop() {
  // 检查ESP8266返回信息（客户端连接/断开）
  if (espSerial.available()) {
    String response = espSerial.readStringUntil('\n');
    response.trim();
    Serial.print("ESP8266返回：");
    Serial.println(response);

    // 检测客户端连接
    if (response.indexOf("CONNECT") > 0) {
      clientID = response.charAt(5) - '0';  // 提取客户端ID
      Serial.println("客户端" + String(clientID) + "已连接");
    }

    // 检测客户端断开
    if (response.indexOf("CLOSED") > 0) {
      Serial.println("客户端已断开");
      clientID = -1;
    }
  }

  // 每3秒向已连接的客户端发送消息
  static unsigned long lastSendTime = 0;
  if (clientID != -1 && millis() - lastSendTime > 3000) {
    String message = "Hello from ESP8266! Time: " + String(millis()/1000) + "s";
    bool sendSuccess = sendToTCPClient(clientID, message);
    
    if (sendSuccess) {
      lastSendTime = millis();
      Serial.println("已发送：" + message);
    } else {
      Serial.println("发送失败，重置客户端连接状态");
      clientID = -1;
    }
  }
}

/**
 * 发送AT指令并返回完整响应
 * @param cmd 要发送的AT指令
 * @param timeout 超时时间（毫秒）
 * @return 包含所有响应内容的字符串（空字符串表示超时）
 */
String sendATCommand(String cmd, int timeout) {
  String response = "";
  espSerial.flush();  // 清空缓冲区
  
  // 发送AT指令
  Serial.print("发送命令：");
  Serial.println(cmd);
  espSerial.println(cmd);
  
  unsigned long startTime = millis();
  
  // 读取所有响应内容
  while (millis() - startTime < timeout) {
    if (espSerial.available()) {
      String line = espSerial.readStringUntil('\n');
      line.trim();
      if (response.length() > 0) {
        response += "\n";  // 多行用换行分隔
      }
      response += line;
    }
  }
  
  // 打印完整响应（调试用）
  if (response.isEmpty()) {
    Serial.println("命令超时，无响应");
  } else {
    Serial.print("命令响应：");
    Serial.println(response);
  }
  
  return response;
}

/**
 * 向TCP客户端发送数据
 * @param clientID 客户端ID（0-4）
 * @param message 要发送的消息内容
 * @return 发送成功返回true，失败返回false
 */
bool sendToTCPClient(int clientID, String message) {
  if (clientID < 0 || clientID > 4) {  // 验证客户端ID有效性
    Serial.println("无效的客户端ID");
    return false;
  }
  
  if (message.isEmpty()) {  // 验证消息非空
    Serial.println("消息内容不能为空");
    return false;
  }
  
  // 1. 发送AT+CIPSEND指令，获取发送权限
  String sendCmd = "AT+CIPSEND=" + String(clientID) + "," + String(message.length());
  String response = sendATCommand(sendCmd, 1000);
  
  // 检查是否收到">"提示符
  if (response.indexOf(">") == -1) {
    Serial.println("未收到发送提示符，发送失败");
    return false;
  }
  
  // 2. 发送实际消息内容
  espSerial.println(message);
  
  // 3. 等待发送成功确认（可选，根据需要添加）
  delay(100);  // 短暂延时等待响应
  String sendResult = espSerial.readStringUntil('\n');
  if (sendResult.indexOf("SEND OK") == -1) {
    Serial.println("消息发送失败：" + sendResult);
    return false;
  }
  
  return true;
}
    